package com.tetris;

import java.awt.Rectangle;

//  █
//███
class Block3 extends Block {
    /**
     * 构造方法。
     */
    public Block3() {
        mBlocks[1][1].mUsed = mBlocks[2][0].mUsed = mBlocks[2][1].mUsed = mBlocks[2][2].mUsed = true;
    }

    /**
     * 擦除。
     */
    protected void erase() {
        final Rectangle rect = new Rectangle();

        switch (mShape) {
            case ONE:
                rect.setRect(Const.GRID_SIZE * (mLine + 1), Const.GRID_SIZE * (mRow + 1), Const.GRID_SIZE, Const.GRID_SIZE);
                super.eraseRect(rect);
                rect.setRect(Const.GRID_SIZE * mLine, Const.GRID_SIZE * (mRow + 2), Const.GRID_SIZE * 3, Const.GRID_SIZE);
                super.eraseRect(rect);
                break;
            case TWO:
                rect.setRect(Const.GRID_SIZE * (mLine + 1), Const.GRID_SIZE * (mRow + 1), Const.GRID_SIZE, Const.GRID_SIZE * 3);
                super.eraseRect(rect);
                rect.setRect(Const.GRID_SIZE * (mLine + 2), Const.GRID_SIZE * (mRow + 2), Const.GRID_SIZE, Const.GRID_SIZE);
                super.eraseRect(rect);
                break;
            case THREE:
                rect.setRect(Const.GRID_SIZE * mLine, Const.GRID_SIZE * (mRow + 2), Const.GRID_SIZE * 3, Const.GRID_SIZE);
                super.eraseRect(rect);
                rect.setRect(Const.GRID_SIZE * (mLine + 1), Const.GRID_SIZE * (mRow + 3), Const.GRID_SIZE, Const.GRID_SIZE);
                super.eraseRect(rect);
            case FOUR:
                rect.setRect(Const.GRID_SIZE * mLine, Const.GRID_SIZE * (mRow + 2), Const.GRID_SIZE, Const.GRID_SIZE);
                super.eraseRect(rect);
                rect.setRect(Const.GRID_SIZE * (mLine + 1), Const.GRID_SIZE * (mRow + 1), Const.GRID_SIZE, Const.GRID_SIZE * 3);
                super.eraseRect(rect);
                break;
        }
    }

    /**
     * 获取底端所在的行数。底端是指方块最下方的有效格。
     * @return 底端所在的行数
     */
    public int getBottom() {
        if (mShape == Shape.ONE) {
            return mRow + 2;
        }
        return mRow + 3;
    }

    /**
     * 获取顶端所在的行数。顶端是指方块最上方的有效格。
     * @return 顶端所在的行数
     */
    public int getTop() {
        if (mShape == Shape.THREE) {
            return mRow + 2;
        }
        return mRow + 1;
    }

    /**
     * 对不能下落的处理。
     */
    protected void handleCannotMoveDown() {
        switch (mShape) {
            case ONE:
                Game.sExistentBlocks[mRow + 1][mLine + 1].mUsed = true;
                Game.sExistentBlocks[mRow + 1][mLine + 1].mColor = mColor;
                for (int j = 0; j <= 2; j++) {
                    Game.sExistentBlocks[mRow + 2][mLine + j].mUsed = true;
                    Game.sExistentBlocks[mRow + 2][mLine + j].mColor = mColor;
                }
                break;
            case TWO:
                Game.sExistentBlocks[mRow + 2][mLine + 2].mUsed = true;
                Game.sExistentBlocks[mRow + 2][mLine + 2].mColor = mColor;
                for (int i = 1; i <= 3; i++) {
                    Game.sExistentBlocks[mRow + i][mLine + 1].mUsed = true;
                    Game.sExistentBlocks[mRow + i][mLine + 1].mColor = mColor;
                }
                break;
            case THREE:
                Game.sExistentBlocks[mRow + 3][mLine + 1].mUsed = true;
                Game.sExistentBlocks[mRow + 3][mLine + 1].mColor = mColor;
                for (int j = 0; j <= 2; j++) {
                    Game.sExistentBlocks[mRow + 2][mLine + j].mUsed = true;
                    Game.sExistentBlocks[mRow + 2][mLine + j].mColor = mColor;
                }
                break;
            case FOUR:
                Game.sExistentBlocks[mRow + 2][mLine].mUsed = true;
                Game.sExistentBlocks[mRow + 2][mLine].mColor = mColor;
                for (int i = 1; i <= 3; i++) {
                    Game.sExistentBlocks[mRow + i][mLine + 1].mUsed = true;
                    Game.sExistentBlocks[mRow + i][mLine + 1].mColor = mColor;
                }
                break;
        }
    }

    /**
     * 下落。
     * @return 成功则返回 true，否则返回 false
     */
    public boolean moveDown() {
        switch (mShape) {
            case ONE:
                if (mRow == 17) {
                    this.handleCannotMoveDown();
                    return false;
                }
                if (Game.sExistentBlocks[mRow + 3][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 1].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                    this.handleCannotMoveDown();
                    return false;
                }
                break;
            case TWO:
                if (mRow == 16) {
                    this.handleCannotMoveDown();
                    return false;
                }
                if (Game.sExistentBlocks[mRow + 4][mLine + 1].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                    this.handleCannotMoveDown();
                    return false;
                }
                break;
            case THREE:
                if (mRow == 16) {
                    this.handleCannotMoveDown();
                    return false;
                }
                if (Game.sExistentBlocks[mRow + 3][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 4][mLine + 1].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                    this.handleCannotMoveDown();
                    return false;
                }
                break;
            case FOUR:
                if (mRow == 16) {
                    this.handleCannotMoveDown();
                    return false;
                }
                if (Game.sExistentBlocks[mRow + 3][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 4][mLine + 1].mUsed) {
                    this.handleCannotMoveDown();
                    return false;
                }
                break;
        }

        return super.moveDown();
    }

    /**
     * 左移。
     */
    public void moveLeft() {
        switch (mShape) {
            case ONE:
                if (mLine == 0) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 2][mLine - 1].mUsed) {
                    return;
                }
                break;
            case TWO:
                if (mLine == -1) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 2][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine].mUsed) {
                    return;
                }
                break;
            case THREE:
                if (mLine == 0) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 2][mLine - 1].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine].mUsed) {
                    return;
                }
                break;
            case FOUR:
                if (mLine == 0) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine].mUsed || 
                    Game.sExistentBlocks[mRow + 2][mLine - 1].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine].mUsed) {
                    return;
                }
                break;
        }

        super.moveLeft();
    }

    /**
     * 右移。
     */
    public void moveRight() {
        switch (mShape) {
            case ONE:
                if (mLine == 7) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine + 2].mUsed || 
                    Game.sExistentBlocks[mRow + 2][mLine + 3].mUsed) {
                    return;
                }
                break;
            case TWO:
                if (mLine == 7) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine + 2].mUsed || 
                    Game.sExistentBlocks[mRow + 2][mLine + 3].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                    return;
                }
                break;
            case THREE:
                if (mLine == 7) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 2][mLine + 3].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                    return;
                }
                break;
            case FOUR:
                if (mLine == 8) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine + 2].mUsed || 
                    Game.sExistentBlocks[mRow + 2][mLine + 2].mUsed || 
                    Game.sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                    return;
                }
                break;
        }

        super.moveRight();
    }

    /**
     * 变形。
     */
    public void transform() {
        switch (mShape) {
            case ONE:
                if (mRow == 17) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 3][mLine + 1].mUsed) {
                    return;
                }
                this.erase();
                mBlocks[2][0].mUsed = false;
                mBlocks[3][1].mUsed = true;
                mShape = Shape.TWO;
                break;
            case TWO:
                if (mLine == -1) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 2][mLine].mUsed) {
                    return;
                }
                this.erase();
                mBlocks[1][1].mUsed = false;
                mBlocks[2][0].mUsed = true;
                mShape = Shape.THREE;
                break;
            case THREE:
                if (mRow == 16) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 1][mLine + 1].mUsed) {
                    return;
                }
                this.erase();
                mBlocks[2][2].mUsed = false;
                mBlocks[1][1].mUsed = true;
                mShape = Shape.FOUR;
                break;
            case FOUR:
                if (mLine == 8) {
                    return;
                }
                if (Game.sExistentBlocks[mRow + 2][mLine + 2].mUsed) {
                    return;
                }
                this.erase();
                mBlocks[3][1].mUsed = false;
                mBlocks[2][2].mUsed = true;
                mShape = Shape.ONE;
                break;
        }

        super.draw();
    }
}
